package pri.black.dogview.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import pri.black.dogview.component.CacheService;
import pri.black.dogview.component.RandomSeed;
import pri.black.dogview.domain.Admin;
import pri.black.dogview.domain.R;
import pri.black.dogview.domain.dto.LoginReq;
import pri.black.dogview.domain.vo.RandResponse;
import pri.black.dogview.security.SecurityContextUtils;
import pri.black.dogview.security.TokenAuthentication;
import pri.black.dogview.security.UserInfoVO;
import pri.black.dogview.service.IAdminService;
import pri.black.dogview.util.ServletContextUtil;

import javax.crypto.Cipher;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

@RestController
public class LoginController {
    private static final Logger log = LoggerFactory.getLogger(LoginController.class);
    @Autowired
    IAdminService adminService;

    @Autowired
    CacheService cacheService;

    @Autowired
    RandomSeed randomSeed;

    private static final
    String loginKey = "login_key";

    private String sign(String origin) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("md5");
            byte[] digest = md5.digest(origin.getBytes());

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < digest.length; i++) {
                String hexString = Integer.toHexString(digest[i] & 0xff);
                if (hexString.length() == 1) {
                    sb.append("0").append(hexString);
                }else {
                    sb.append(hexString);
                }
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("md5 error", e);
        }


        return null;
    }

    @GetMapping("/rand")
    R rand(HttpServletRequest request){
        String ip = ServletContextUtil.getIP();

        Long rand = randomSeed.rand();
        LocalDateTime now = LocalDateTime.now();
        int minute = now.getMinute();

        Long result = rand + minute;
        log.warn("gen rand from {},{}",ip, result);

        RandResponse randResponse = new RandResponse();
        randResponse.setRand(rand);
        randResponse.setCurrentTime(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        cacheService.set(loginKey,result);

        return R.ok(randResponse);
    }

    @PostMapping("/login")
    R login(@RequestBody LoginReq req){


        String ip = ServletContextUtil.getIP();
        log.warn("login from ip address {}", ip);

        if (req.getRand() != null) {
            log.error("来自{}非法访问",ip);
            return R.fail("用户名密码错误");
        }

        Admin admin = adminService.lambdaQuery().eq(Admin::getUsername, req.getUsername()).one();

        String lockKey = "login_lock_" + ip;
        Object loginLock = cacheService.get(lockKey);
        if (loginLock == null) {
            loginLock = 1L;
            cacheService.set(lockKey, loginLock);
        }
        Long locktime = (Long) loginLock;
        if (locktime > 10L) {
            return R.fail("你已被禁止登录");
        }
//
//
//        if (locktime > 10) {
//            File lock = new File("lock_" + ip);
//            if (lock.exists()) {
//                boolean reset = false;
//                try ( BufferedReader bufferedReader = new BufferedReader(new FileReader(lock));
//                ){
//                   String line = bufferedReader.readLine();
//                    if (StringUtils.isEmpty(line)) {
//                        reset = true;
//                    }
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//                if (reset) {
//                    cacheService.remove(lockKey);
//                    lock.delete();
//                    return R.fail("block has been reset");
//                }else {
//                    cacheService.set(lockKey, ++locktime);
//                    appendLockLog(lock, locktime + "," + ip + "\n");
//                }
//            }else {
//                cacheService.set(lockKey, ++locktime);
//                log.warn("lock file {}",lock.getAbsolutePath());
//                appendLockLog(lock, locktime + "," + ip + "\n");
//            }
//
//            return R.fail("you are being block");
//        }
//
//        Long rand = req.getRand();
//        if (rand == null || !rand.equals(cacheService.get(loginKey))) {
//            cacheService.set(lockKey, ++locktime);
//            return R.fail("you are not allowed");
//        }

        if (admin == null) {
            log.error("账号不存在 {}", req.getUsername());
            cacheService.set(lockKey, ++locktime);
            return R.fail("login fail");
        }

        if (!req.getPassword().equals(admin.getPassword())) {
            log.error("密码不正确：{}", req.getPassword());
            cacheService.set(lockKey, ++locktime);
            return R.fail("login fail");
        }

        cacheService.set(lockKey, 0L);

        String token = sign(System.currentTimeMillis() + admin.getUsername());

        cacheService.set("token:" + token, admin.getId());

//        admin.setToken(token);
        admin.setLoginTime(LocalDateTime.now());
        adminService.updateById(admin);
        return R.ok(token);
    }

    private static void appendLockLog(File lock, String locktime) {
        try (
                BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(lock, true));
        ) {
            bufferedWriter.append(locktime);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("info")
    R info() {
        Admin admin = SecurityContextUtils.admin();
        if (admin == null) {
            return R.fail();
        }
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setName(admin.getUsername());
        userInfoVO.setRoles(List.of("admin"));
        userInfoVO.setIntroduction("");
        userInfoVO.setAvatar(null);
        return R.ok(userInfoVO);
    }

    @PostMapping("logout")
    R logout(){
        Long id = SecurityContextUtils.admin().getId();
        adminService.logout(id);
        return R.ok();
    }
}
